package cn.iocoder.yudao.module.signature.service.application;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.signature.appconnect.util.IpaInfoExtractorUtil;
import cn.iocoder.yudao.module.signature.controller.admin.application.vo.ApplicationInfoPageReqVO;
import cn.iocoder.yudao.module.signature.controller.admin.application.vo.ApplicationInfoRespVO;
import cn.iocoder.yudao.module.signature.controller.admin.application.vo.ApplicationInfoSaveReqVO;
import cn.iocoder.yudao.module.signature.controller.admin.application.vo.IpaInfoExtractorRespVO;
import cn.iocoder.yudao.module.signature.dal.dataobject.application.ApplicationInfoDO;
import cn.iocoder.yudao.module.signature.dal.mysql.application.ApplicationInfoMapper;
import cn.iocoder.yudao.module.signature.enums.AppType;
import cn.iocoder.yudao.module.signature.enums.EnableType;
import cn.iocoder.yudao.module.signature.model.IpaInfoModel;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.dd.plist.PropertyListFormatException;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.SAXException;

import javax.annotation.Resource;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.text.ParseException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.signature.enums.ErrorCodeConstants.APPLICATION_INFO_NOT_EXISTS;

/**
 * 应用 Service 实现类
 *
 * @author base
 */
@Service
@Slf4j
@Validated
public class ApplicationInfoServiceImpl implements ApplicationInfoService {

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private MemberUserApi memberUserApi;

    @Resource
    private ApplicationInfoMapper applicationInfoMapper;

    @Resource
    private FileApi fileApi;

    @Override
    public Long createApplicationInfo(ApplicationInfoSaveReqVO createReqVO) {
        // 插入
        ApplicationInfoDO applicationInfo = BeanUtils.toBean(createReqVO, ApplicationInfoDO.class);
        applicationInfo.setApplicationStatus(String.valueOf(EnableType.ENABLE.getType()));
        applicationInfoMapper.insert(applicationInfo);

        String iconId = CharSequenceUtil.subAfter(applicationInfo.getIconImg(), "/get/", false);
        String ipaId= CharSequenceUtil.subAfter(applicationInfo.getApplicationUrl(), "/get/", false);
        fileApi.moveFile(iconId,"icon");
        fileApi.moveFile(ipaId,"ipa");
        // 返回
        return applicationInfo.getId();
    }

    @Override
    public void updateApplicationInfo(ApplicationInfoSaveReqVO updateReqVO) {
        // 校验存在
        validateApplicationInfoExists(updateReqVO.getId());
        // 更新
        ApplicationInfoDO updateObj = BeanUtils.toBean(updateReqVO, ApplicationInfoDO.class);
        if (!Objects.equals(updateReqVO.getUserId(), updateObj.getUserId())) {
            return;
        }
        String iconId = CharSequenceUtil.subAfter( updateObj.getIconImg(), "/get/", false);
        fileApi.moveFile(iconId,"icon");
        applicationInfoMapper.updateById(updateObj);
    }

    @Override
    public void deleteApplicationInfo(Long id) {
        // 校验存在
        validateApplicationInfoExists(id);
        // 删除
        applicationInfoMapper.deleteById(id);
    }

    private void validateApplicationInfoExists(Long id) {
        if (applicationInfoMapper.selectById(id) == null) {
            throw exception(APPLICATION_INFO_NOT_EXISTS);
        }
    }

    @Override
    public ApplicationInfoDO getApplicationInfo(Long id) {
        return applicationInfoMapper.selectById(id);
    }

    @Override
    public ApplicationInfoDO getApplicationInfo(Long id, Long userId) {
        applicationInfoMapper.selectOne(new LambdaQueryWrapperX<ApplicationInfoDO>().eq(ApplicationInfoDO::getId, id).eq(ApplicationInfoDO::getUserId, userId));
        return null;
    }

    @Override
    public PageResult<ApplicationInfoDO> getApplicationInfoPage(ApplicationInfoPageReqVO pageReqVO) {
        if(StringUtils.equals(pageReqVO.getBelongType(), String.valueOf(AppType.PUBLIC.getType()))){
            pageReqVO.setUserId(null);
        }
        if (StringUtils.isNotEmpty(pageReqVO.getUserName())){
            List<MemberUserRespDTO> userListByNickname = memberUserApi.getUserListByNickname(pageReqVO.getUserName());
            pageReqVO.setUserIds(userListByNickname.stream().map(MemberUserRespDTO::getId).collect(Collectors.toList()));
        }
        PageResult<ApplicationInfoDO> page = applicationInfoMapper.selectPage(pageReqVO);
        if(CollectionUtil.isNotEmpty(page.getList())){
            List<MemberUserRespDTO> memberList = memberUserApi.getUserList(page.getList().stream().map(applicationInfoDO -> Long.valueOf(applicationInfoDO.getCreator()) ).collect(Collectors.toList()));

            page.getList().forEach(applicationInfoDO -> {
                    memberList.stream().filter(user -> Objects.equals(user.getId(), Long.valueOf(applicationInfoDO.getCreator()))).findFirst().ifPresent(user ->{
                        applicationInfoDO.setBatchFlag(user.getBatchFlag());
                        applicationInfoDO.setBatchNum(user.getBatchNum());
                        applicationInfoDO.setUpdateName(user.getNickname());
                    });
            });
        }

        return page;
    }

    @Override
    public List<ApplicationInfoRespVO> getInstallAppList() {
        List<ApplicationInfoDO> installAppList = applicationInfoMapper.getInstallAppList();
        if(CollectionUtil.isEmpty(installAppList)){
            return Lists.newArrayList();
        }

        return BeanUtil.copyToList(installAppList, ApplicationInfoRespVO.class);
    }

    /**
     * 获取应用ipa包信息
     *
     * @param file
     * @return
     */
    @Override
    public IpaInfoExtractorRespVO getIpaInfoExtractor(MultipartFile file) {
        IpaInfoModel ipaInfo = null;
        try {
            ipaInfo = IpaInfoExtractorUtil.getIpaInfo(file, fileApi);
        } catch (IOException | PropertyListFormatException | ParseException | ParserConfigurationException |
                 SAXException e) {
            log.info("getIpaInfoExtractor error", e);
            throw exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
        return BeanUtils.toBean(ipaInfo, IpaInfoExtractorRespVO.class);
    }

    @Override
    public void delete(List<Long> idList,Long userId) throws Exception {
        Assert.notEmpty(idList, "删除数据时，主键集合不能为空！");
        List<ApplicationInfoDO> applicationInfoDOS = applicationInfoMapper.selectBatchIds(idList);
        if(null!=userId){
            applicationInfoDOS = applicationInfoDOS.stream().filter(applicationInfoDO -> Objects.equals(applicationInfoDO.getUserId(), userId)).collect(Collectors.toList());
        }
        Assert.notEmpty(applicationInfoDOS, "删除数据时，未查询到需要删除的数据！");
        applicationInfoMapper.deleteByIds(applicationInfoDOS.stream().map(ApplicationInfoDO::getId).collect(Collectors.toList()));
        for (ApplicationInfoDO applicationInfoDO : applicationInfoDOS) {
            String applicationUrl = applicationInfoDO.getApplicationUrl();
            String appId = CharSequenceUtil.subAfter(applicationUrl, "/get/", false);
            fileApi.deleteFile(Long.valueOf(appId));
//            fileApi.deleteFile(Long.valueOf(CharSequenceUtil.subAfter(applicationInfoDO.getIconImg(), "/get/", false)));

        }

    }

    @Override
    public void enable(List<Long> idList) {
        Assert.notEmpty(idList, "启用数据时，主键集合不能为空！");
        List<ApplicationInfoDO> applicationInfoDOS = applicationInfoMapper.selectBatchIds(idList);
        applicationInfoDOS.forEach(applicationInfoDO -> applicationInfoDO.setApplicationStatus(String.valueOf(EnableType.ENABLE.getType())));
        applicationInfoMapper.updateBatch(applicationInfoDOS);
    }

    @Override
    public void disable(List<Long> idList) {
        Assert.notEmpty(idList, "禁用数据时，主键集合不能为空！");
        List<ApplicationInfoDO> applicationInfoDOS = applicationInfoMapper.selectBatchIds(idList);
        applicationInfoDOS.forEach(applicationInfoDO -> applicationInfoDO.setApplicationStatus(String.valueOf(EnableType.DISABLE.getType())));
        applicationInfoMapper.updateBatch(applicationInfoDOS);

    }


}